package ie.dit.reg08.manager;

//these lines import the JAXP APIs
import javax.xml.parsers.*;
import org.xml.sax.SAXException;  

//import org.xml.sax.SAXParseException;
//these lines import the api to read the sample XML file and identify errors:

import java.io.File;
import java.io.IOException;

//these lines import the W3C definition for a DOM and DOM exceptions:
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

//import org.w3c.dom.DOMException;
//import org.w3c.dom.NamedNodeMap;
//import org.w3c.dom.Node;

import java.io.*; //for file handling
import java.util.*;

import ie.dit.reg08.realiser.*;



public class CorpusIOManager {

    //static final String TRAININGCORPUS = "07data";

    /*
     * TODO: need to create a proper test corpus and update the TESTCORPUS to reflect this
     */
	static final String TESTCORPUSTASK1 = "./REG-Challenge-Pack/Training-Data/TUNA/train";
	
	static final String TESTCORPUSTASK3 = "./REG-Challenge-Pack/Training-Data/TUNA/train";

	static final String OUTPUTDIRTASK1 = "./output/task1";
	
	static final String OUTPUTDIRTASK3 = "./output/task3";

	Document document;
	
	
	
	//Vector<Trial> vTrials;
	
	/*
	 * Takes a file and parses it into an XML Dom object using a DocumentBuilder
	 */
	public void initDocument(File f) {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		//factory.setValidating(true);
	    //factory.setNamespaceAware(true);		
		
		try {
			  System.out.println("file path = " + f.toString());
			  if(!f.exists())
				  System.err.println("file does not exist");
			  
			  DocumentBuilder builder = factory.newDocumentBuilder();  
			  document = builder.parse( f );
			  System.out.println("init document: document = ");
			  System.out.println(document.toString());
			  
		} 
		catch (SAXException sxe) {
			System.err.println("init document: SASException");
			// Error generated during parsing
			Exception x = sxe;
			if (sxe.getException() != null)
				x = sxe.getException();
			x.printStackTrace();
		} catch (ParserConfigurationException pce) {
			System.err.println("init document: Parser configuration exception");

			// Parser with specified options can't be built
			pce.printStackTrace();
		} catch (IOException ioe) {
			System.err.println("init document: IO error");

			// I/O error
			ioe.printStackTrace();
		}		
	}

	/*
	 * If arg1 = name of a file this function parses the file into a trial data structure.
	 * If arg1 = a directory the this function iterates over the files in the directory and parses
	 * each file into a Trial data structure and for each subdirectory it recursively calls itself.
	 * In both cases the Trial data structures constructed are stored in the vTrials vector.
	 * Arg2 is a boolean that controls whether or not the function outputs the
	 * name of the dir/files it is processing to stdout
	 */
	public Vector<Trial> processCorpus(String s) {
			
		//System.out.println("processCorpus: corpus = " + s);
		
		Vector<Trial> vTrials = new Vector<Trial>();
		
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		//factory.setValidating(true);
	    //factory.setNamespaceAware(true);	
		DocumentBuilder builder = null;
		try {
			 builder = factory.newDocumentBuilder();  
		} catch (ParserConfigurationException pce) {
			// Parser with specified options can't be built
			pce.printStackTrace();
		} catch (Exception e) {
			System.out.println(e.toString());
		}
		
		File path = new File(s);
		
		if(path.isDirectory()) {
			//filter the list of returned files to include xml files and exclude system files
		    FilenameFilter filter = new FilenameFilter() {
		        public boolean accept(File dir, String name) {
		        		return (!name.startsWith("."));
		        }
		    };
		    String[] children = path.list(filter);
			if(children == null) {
				System.err.println("Directory is empty!");
			} else {
				for(int i =0; i<children.length; i++) {
					String filename = children[i];	
					filename = path + "/" + filename;
					File f = new File(filename);
					if(f.isDirectory()) {
						vTrials.addAll(processCorpus(filename));
					} else {
						//System.out.println("processCorpus: processing file " + filename);

						if(filename.endsWith("dtd")) {
			
						} else if(filename.endsWith("xml")) {													
							try {
								  if(!f.exists())
									  System.err.println("file does not exist");
								  
								  document = builder.parse( f );
								  
							} 
							catch (SAXException sxe) {
								// Error generated during parsing
								Exception x = sxe;
								if (sxe.getException() != null)
									x = sxe.getException();
								x.printStackTrace();
							} catch (IOException ioe) {
								// I/O error
								ioe.printStackTrace();
							} catch (Exception e) {
								e.printStackTrace();
							}

							Node n;
							NodeList list = document.getChildNodes();
							for(int j =0; j < list.getLength(); j++) {
								n = list.item(j);
								if(n.hasChildNodes()) {
									vTrials.add(new Trial(n));				
									break;
								}
							}
								
						} else {
							System.err.println(filename + " not xml file!");
						}
					}
				}
			}
			
		} else {
			System.err.println("processCorpus: unknown file type!!" + filename);
		}		
		
		return vTrials;
	}
	
	/* 
	 * This function iterates over the vTrials vector and outputs the data stored in
	 * each of the vectors elements (Trial objects)
	 */
	public void outputCorpusData(Vector<Trial> vTrials) {
		Iterator<Trial> i = vTrials.iterator();
		while(i.hasNext()) {
			(i.next()).outputTrialDescription();
		}
	}

	
	/*
	 * Output the descriptions generated to files.
	 * Arg1 = (String) path of the corpus data. Descriptions written to a dir "systemdescrioptions" 
	 * in the parent directory of the corpus. This dir is created if need be.
	 */
	public void outputDescriptions(String outputdir, Vector<greInterface> vGreInterface) {
		
		Iterator<greInterface> j;
		greInterface greInt;
		PrintWriter OUT;
		File o;
		try {			
			o = new File(outputdir);
			
			if(!o.exists()) {
				if(o.mkdir()) {
					System.out.println("Created dir: " + o.toString());
				} else {
					System.err.println("Failed to create output dir: " + o.toString());
					System.exit(1);
				}
			}
			
			j = vGreInterface.iterator();
			while(j.hasNext()) {
				greInt = j.next();
				OUT = new PrintWriter(new FileWriter(o.toString() + "/" + greInt.getID() +".xml"));
				OUT.print(greInt.xmlDescription());
				OUT.close();
			}			
		} catch (SecurityException e) {
			System.err.println("outputDescriptions: Unable to delete outputdir  (" + e.getMessage() + ")");
			System.exit(1);
		}
		catch(IOException e){
			System.err.println("outputDescriptions: " + e.getMessage());
		}

	}
	
	public CorpusIOManager() {
		
	}

	
	

}
